package com.weir.workdemo.work01.future.model;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * @author weir
 */
@Slf4j
public class Main {
    public static ExecutorService executorService = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws JsonProcessingException {
        //构建测试使用的节点
        Node<String> parent = buildNodes();
        log.info("root ===> {}", new ObjectMapper().writeValueAsString(parent));
        //同步遍历方式
        // traverse(parent, 0);
            traverseAsyn(parent, 0);
        try {
            TimeUnit.SECONDS.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

    private static void traverseAsyn(Node<String> parent, int level) {
        List<Node<String>> children = parent.getChildren();
        if (children == null || children.isEmpty()) {
            return;
        }
        int finalLevel = level++;
        int mid = children.size() / 2;
        CompletableFuture.runAsync(() -> {
            for (int i = 0; i < mid; i++) {
                doTask(children, finalLevel, i);
            }
        });
        CompletableFuture.runAsync(() -> {
            for (int i = mid; i < children.size(); i++) {
                doTask(children, finalLevel, i);
            }
        }, executorService);
    }

    private static void doTask(List<Node<String>> children, int finalLevel, int i) {
        Node<String> item = children.get(i);
        List<Node<String>> grandson = item.getChildren();
        if (grandson != null && !grandson.isEmpty()) {
            traverse(item, finalLevel);
        }
        log.info("{}", prettyPrint(finalLevel) + item.getData());
    }

    private static void traverse(Node<String> parent, int level) {
        List<Node<String>> children = parent.getChildren();
        if (children == null || children.isEmpty()) {
            return;
        }
        level++;
        for (int i = 0; i < children.size(); i++) {
            doTask(children, level, i);
        }
    }

    private static String prettyPrint(int level) {
        return IntStream.rangeClosed(0, level).mapToObj(l -> "\t").collect(Collectors.joining());
    }

    private static Node<String> buildNodes() {
        return new Node<>("A0", buildChildren('B', 2, 4));
    }

    private static List<Node<String>> buildChildren(char b, int i, int maxFloor) {
        return IntStream.range(0, i)
                .filter(value -> i <= maxFloor)
                .mapToObj(j -> new Node<>(b + "" + j, i == maxFloor ? null : buildChildren((char) (b + 1), i + 1, maxFloor)))
                .collect(Collectors.toList());
    }
}
